#ifndef THREADSAFESTRINGMAP_HPP
#define THREADSAFESTRINGMAP_HPP

#include <stdio.h>
#include <string.h>
#include <uthash.h>
#include "rwlock.h"
namespace thmar
{
    // 基于 uthash 的 hashmap 实现
    // Key为字符串，Value为任意类型
    // 线程安全，支持并发读写
    // Usage:
    // ThreadSafeStringMap<int, int> map;
    // map.insert(1, 2);
    // int value;
    // if (map.find(1, value)) {
    //     printf("Found value: %d\n", value);
    // } else {
    //     printf("Key not found\n");
    // }
    // map.erase(1);
    // map.clear();
    template <typename V>
    class ThreadSafeStringMap
    {
    public:
        ThreadSafeStringMap() : table(nullptr)
        {
            rwlock_init(&lock);
        }
        ~ThreadSafeStringMap()
        {
            clear();
            rwlock_destroy(&lock);
        }

        void insert(const char *key, const V &value)
        {
            if (key)
            {
                rwlock_lock_write(&lock);
                Item *item = new Item;
                item->key = strdup(key);
                item->value = value;
                HASH_ADD_STR(table, key, item);
                rwlock_unlock_write(&lock);
            }
        }
        bool find(const char *key, V &value) const
        {
            if (!key)
            {
                return false;
            }
            rwlock_lock_read(&lock);
            Item *item;
            HASH_FIND_STR(table, key, item);
            bool found = (item != nullptr);
            if (found)
            {
                value = item->value;
            }
            rwlock_unlock_read(&lock);
            return found;
        }
        bool contains(const char *key) const
        {
            if (!key)
            {
                return false;
            }
            rwlock_lock_read(&lock);
            V value;
            bool found = find(key, value);
            rwlock_unlock_read(&lock);
            return found;
        }
        void erase(const char *key)
        {
            if (key)
            {
                rwlock_lock_write(&lock);
                Item *item;
                HASH_FIND_STR(table, key, item);
                if (item)
                {
                    HASH_DEL(table, item);
                    delete item;
                }
                rwlock_unlock_write(&lock);
            }
        }
        void clear()
        {
            rwlock_lock_write(&lock);
            Item *current_item, *tmp;
            HASH_ITER(hh, table, current_item, tmp)
            {
                HASH_DEL(table, current_item);
                delete current_item;
            }
            table = nullptr;
            rwlock_unlock_write(&lock);
        }
        bool empty() const
        {
            rwlock_lock_read(&lock);
            bool empty = (table == nullptr);
            rwlock_unlock_read(&lock);
            return empty;
        }
        size_t size() const
        {
            rwlock_lock_read(&lock);
            size_t size = HASH_COUNT(table);
            rwlock_unlock_read(&lock);
            return size;
        }

    private:
        struct Item
        {
            char *key;
            V value;
            UT_hash_handle hh; // Makes this structure hashable
            ~Item()
            {
                free(key);
            }
        };

        Item *table;           // Hash table
        mutable rwlock_t lock; // 读写锁
    };
    // 基于 uthash 的 hashmap 实现
    // Key为int，Value为任意类型
    // 线程安全，支持并发读写
    // Usage:
    // ThreadSafeStringMap<int, int> map;
    // map.insert(1, 2);
    // int value;
    // if (map.find(1, value)) {
    //     printf("Found value: %d\n", value);
    // } else {
    //     printf("Key not found\n");
    // }
    // map.erase(1);
    // map.clear();
    template <typename V>
    class ThreadSafeIntMap
    {
    public:
        ThreadSafeIntMap() : table(nullptr)
        {
            rwlock_init(&lock);
        }
        ~ThreadSafeIntMap()
        {
            clear();
            rwlock_destroy(&lock);
        }

        void insert(int key, const V &value)
        {
            rwlock_lock_write(&lock);
            Item *item = new Item;
            item->key = key;
            item->value = value;
            HASH_ADD_INT(table, key, item);
            rwlock_unlock_write(&lock);
        }
        bool find(int key, V &value) const
        {
            rwlock_lock_read(&lock);
            Item *item;
            HASH_FIND_INT(table, &key, item);
            bool found = (item != nullptr);
            if (found)
            {
                value = item->value;
            }
            rwlock_unlock_read(&lock);
            return found;
        }
        bool contains(int key) const
        {
            rwlock_lock_read(&lock);
            V value;
            bool found = find(key, value);
            rwlock_unlock_read(&lock);
            return found;
        }
        void erase(int key)
        {
            rwlock_lock_write(&lock);
            Item *item;
            HASH_FIND_INT(table, &key, item);
            if (item)
            {
                HASH_DEL(table, item);
                delete item;
            }
            rwlock_unlock_write(&lock);
        }
        void clear()
        {
            rwlock_lock_write(&lock);
            Item *current_item, *tmp;
            HASH_ITER(hh, table, current_item, tmp)
            {
                HASH_DEL(table, current_item);
                delete current_item;
            }
            table = nullptr;
            rwlock_unlock_write(&lock);
        }
        bool empty() const
        {
            rwlock_lock_read(&lock);
            bool empty = (table == nullptr);
            rwlock_unlock_read(&lock);
            return empty;
        }
        size_t size() const
        {
            rwlock_lock_read(&lock);
            size_t size = HASH_COUNT(table);
            rwlock_unlock_read(&lock);
            return size;
        }

    private:
        struct Item
        {
            int key;
            V value;
            UT_hash_handle hh; // Makes this structure hashable
        };

        Item *table;           // Hash table
        mutable rwlock_t lock; // 读写锁
    };
} // namespace thmar
#endif // THREADSAFESTRINGMAP_HPP